package com.hzhanghuan.recyclerview.adapter;

import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

/**
 * RecyclerView的适配器,某些时候需要分模块添加数据,这个适配器提供了模块化的添加数据
 * Created by Administrator on 2016/6/7.
 */
public abstract class ModuleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private ItemManager itemManager;


    public void addModule(Module module) {
        module.setAdapter(this);
        getItemManager().addModule(module);
    }


    @Override
    public int getItemCount() {
        return getItemManager().getItemCount();
    }


    /**
     * 获取Item的集合管理器
     *
     * @return
     */
    public ItemManager getItemManager() {
        if (itemManager == null) {
            itemManager = new ItemManager();
        }
        return itemManager;
    }


    /**
     * 这个类用于管理所有item
     */
    public static class ItemManager {

        /**
         * 找到指定位置是属于那个Module的
         *
         * @param position
         * @return
         */
        public Module findModuleFromPosition(int position) {
            List<Module<?>> modules = getModules();
            int count = 0;
            for (int i = 0; i < modules.size(); i++) {
                count += modules.get(i).getCount();
                if (count > position) {
                    return modules.get(i);
                }
            }
            return null;
        }


        //存放了所有模型组

        private List<Module<?>> modules = new ArrayList<>();


        /**
         * 取出所有的module
         *
         * @return
         */
        public List<Module<?>> getModules() {
            return modules;
        }


        public <T> Module<T> addModule(Module<T> module) {
            modules.add(module);
            return module;
        }


        public <T> Module<T> addModule(Module<T> module, int index) {
            modules.add(index, module);
            return module;
        }


        public int getModuleCount() {
            return modules.size();
        }


        /**
         * 取出module的Item列表
         *
         * @param module
         * @param <T>
         * @return
         */
        public <T> List<T> getModulItems(Module<T> module) {
            return module.getItemList();
        }


        /**
         * 获取在某个module之前的item数量
         *
         * @param module
         * @return
         */
        public int getModuleCountBefore(Module module) {
            int index = getModules().indexOf(module);
            if (index == -1) {
                return -1;
            }
            int size = 0;
            for (int i = 0; i < index; i++) {
                size += getModules().get(i).getCount();
            }
            return size;
        }


        /**
         * 获取item数量
         *
         * @return
         */
        public int getItemCount() {
            int size = modules.size();
            int count = 0;
            for (int i = 0; i < size; i++) {
                Module<?> module = modules.get(i);
                List<?> items = module.getItemList();
                count += items.size();
            }
            return count;
        }

    }


    /**
     * @param <T>
     */
    public static final class Module<T> {

        private List<T> itemList = new ArrayList<>();
        private ModuleAdapter adapter;
        private int type;


        public Module(int type) {
            this.type = type;
        }


        /**
         * 创建指定类型的Module
         *
         * @param cls
         * @param <T>
         * @return
         */
        public static <T> Module<T> createModule(Class<T> cls, int type) {
            return new Module<>(type);
        }


        /**
         * 获取Module的类型
         *
         * @return
         */
        public int getType() {
            return type;
        }


        /**
         * 这个方法在Module添加到适配器中后将会调用
         *
         * @param adapter
         */
        protected final void setAdapter(ModuleAdapter adapter) {
            this.adapter = adapter;
        }


        /**
         * 获取item,返回所有在这个Module中的数据
         *
         * @return
         */
        public List<T> getItemList() {
            return itemList;
        }


        /**
         * module的Item数量
         *
         * @return
         */
        public int getCount() {
            return itemList.size();
        }


        /**
         * 找到指定位置在适配器中的位置
         *
         * @param index 在这个Module中的位置
         * @return 在适配器中的位置
         */
        public int findAdapterPositionFromModuleIndex(int index) {
            guaranteeAdapter();
            int count = adapter.getItemManager().getModuleCountBefore(this);
            return count + index;
        }


        /**
         * 根据适配器中的位置取出module的index
         *
         * @param position 在适配器中的位置
         * @return 在这个Module中的位置
         */
        public int findModuleIndexFromAdapterPosition(int position) {
            guaranteeAdapter();
            return position - adapter.getItemManager().getModuleCountBefore(this);
        }


        /**
         * 这个方法用于确保已添加到适配器中
         */
        private void guaranteeAdapter() {
            if (adapter == null) {
                throw new IllegalStateException("必须将Module添加到适配器");
            }
        }


        /**
         * 添加新的数据到Module中
         *
         * @param item   新的数据
         * @param notify 是否通知适配器更新
         * @return 在Module中的位置
         */
        public synchronized int addItem(T item, boolean notify) {
            itemList.add(item);
            int index = itemList.size();
            if (notify) {
                adapter.notifyItemInserted(findAdapterPositionFromModuleIndex(index));
            }
            return index;
        }


        /**
         * 添加一组数据到Module中
         *
         * @param itemList 需要添加的数据
         * @param notify   是否通知更新数据
         */
        public synchronized void addItems(List<T> itemList, boolean notify) {
            int start = this.itemList.size();
            this.itemList.addAll(itemList);
            if (notify) {
                start = findAdapterPositionFromModuleIndex(start);
                adapter.notifyItemRangeInserted(start, itemList.size());
            }
        }


        /**
         * 快速添加一组数据到Module中，并通知观察者
         *
         * @param itemList
         */
        public void addItems(List<T> itemList) {
            addItems(itemList, true);
        }


        /**
         * 插入数据并通知适配器更新
         *
         * @param item
         * @return
         */
        public int addItem(T item) {
            return addItem(item, true);
        }


        /**
         * 根据在Module中的位置来移除item并通知观察者
         *
         * @param index  在Module中的位置
         * @param notify 是否通知
         * @return 移除的Item
         */
        public synchronized T removeItemFromIndex(int index, boolean notify) {
            T item = itemList.remove(index);
            if (notify) {
                adapter.notifyItemRemoved(findAdapterPositionFromModuleIndex(index));
            }
            return item;
        }


        /**
         * 根据在Module中的位置来移除item
         *
         * @param index 在Module中的位置
         * @return 移除的Item
         */
        public T removeItemFromIndex(int index) {
            return removeItemFromIndex(index, true);
        }


        /**
         * 根据适配器中的位置移除item并通知观察者
         *
         * @param position 在适配器中的位置
         * @param notify   是否通知
         * @return 移除的Item
         */
        public synchronized T removeItemFromAdapterPosition(int position, boolean notify) {
            int index = findModuleIndexFromAdapterPosition(position);
            T item = itemList.remove(index);
            if (notify) {
                adapter.notifyItemRemoved(position);
            }
            return item;
        }


        /**
         * 根据适配器中的位置移除item
         *
         * @param position 在适配器中的位置
         * @return
         */
        public T removeItemFromAdapterPosition(int position) {
            return removeItemFromAdapterPosition(position, true);
        }


        /**
         * 根据在Module中的位置获取Item
         *
         * @param index
         * @return
         */
        public T getItemFormIndex(int index) {
            return itemList.get(index);
        }


        /**
         * 根据在适配器中的位置获取Item
         *
         * @param position
         * @return
         */
        public T getItemFromAdapterPosition(int position) {
            int count = adapter.getItemManager().getModuleCountBefore(this);
            return getItemFormIndex(position - count);
        }


        /**
         * 清除数据
         *
         * @param notify
         */
        public void clear(boolean notify) {
            int end = getCount();
            getItemList().clear();
            if (notify) {
                adapter.notifyItemRangeRemoved(0, end);
            }
        }


    }

}
